﻿#region Declaration

//------------------------------------------------------------------------------
// Compas Information Techonoly Co., Ltd
// The Initial Developer of the Original Code is CompasSolutions.
// All Rights Reserved.
// 
// Contributor(s): _______. 
//------------------------------------------------------------------------------

#endregion

#region Using Directives

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

#endregion

namespace QuickDev.Common.Security
{
    /// <summary>
    /// Provides methods for generating cryptographically-strong random numbers.
    /// </summary>
    public static class RNG
    {
        private static byte[] randb = new byte[4];
        private static RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
       
        /// <summary>
        /// Generates a random non-negative number.  
        /// </summary>
        public static int Next()
        {
            rand.GetBytes( randb );
            int value = BitConverter.ToInt32( randb , 0 );
            if ( value < 0 ) value = -value;
            return value;
        }
        /// <summary>
        /// Generates a random non-negative number less than or equal to max.
        /// </summary>
        /// <param name="max">The maximum possible value.</param>
        public static int Next( int max )
        {
            rand.GetBytes( randb );
            int value = BitConverter.ToInt32( randb , 0 );
            value = value % ( max + 1 ); // % calculates remainder
            if ( value < 0 ) value = -value;
            return value;
        }

        /// <summary>
        /// Generates a random non-negative number bigger than or equal to min and less than or
        ///  equal to max.
        /// </summary>
        /// <param name="min">The minimum possible value.</param>
        /// <param name="max">The maximum possible value.</param>
        public static int Next( int min , int max )
        {
            int value = Next( max - min ) + min;
            return value;
        }

        /// <summary>
        /// Gets the random string.
        /// </summary>
        /// <returns></returns>
        public static string RandomString()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append( RandomString( 4 , false ) );
            builder.Append( RandomInt( 1000 , 9999 ) );
            builder.Append( RandomString( 2 , false ) );
            return builder.ToString();
        }

        /// <summary>
        /// Generates a random string.
        /// </summary>
        /// <param name="length">The length.</param>
        /// <returns></returns>
        public static string RandomString( int length )
        {
            string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
            string randomString = string.Empty;
            if ( length > 0 )
            {
                Random rnd = new Random();
                for ( int i = 0 ; i < length ; i++ )
                {
                    randomString += chars[rnd.Next( chars.Length )];
                }
            }
            return randomString;
        }

        /// <summary>
        /// Randoms the string.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="lowerCase">if set to <c>true</c> [lower case].</param>
        /// <returns></returns>
        private static string RandomString( int size , bool lowerCase )
        {
            StringBuilder builder = new StringBuilder();
            Random random = new Random();
            for ( int i = 0 ; i < size ; i++ )
            {
                char ch = Convert.ToChar( Convert.ToInt32( 26 * random.NextDouble() + 65 ) );
                builder.Append( ch );
            }
            if ( lowerCase )
                return builder.ToString().ToLower();
            return builder.ToString();
        }

        /// <summary>
        /// Randoms the int.
        /// </summary>
        /// <param name="min">The min.</param>
        /// <param name="max">The max.</param>
        /// <returns></returns>
        private static int RandomInt( int min , int max )
        {
            Random random = new Random();
            return random.Next( min , max );
        }

        /// <summary>
        /// Generates a 4 by 4 masked string.
        /// </summary>
        /// <returns></returns>
        public static string Generate4By4MaskedString()
        {
            string chars = "1234567890";
            string randomString = string.Empty;
            Random rnd = new Random();
            for ( int i = 1 ; i <= 16 ; i++ )
            {
                randomString += chars[rnd.Next( chars.Length )];
                if ( i < 16 && i % 4 == 0 )
                {
                    randomString += "-";
                }
            }
            return randomString;
        }
    }
}
